package org.rupa.core.registry.center;

import lombok.SneakyThrows;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;
import org.rupa.common.constant.ZkPathConstant;
import org.rupa.common.model.RegistryCenterInfo;
import org.rupa.common.model.ServiceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 实现基础的注册中心需要的基础方法
 */
public abstract class AbstractRegistryCenterFactory extends AbstractRegistryCenterHeartbeatServer implements RegistryCenterFactory, InitializingBean, DisposableBean {
    private CuratorFramework curatorFramework;

    public Logger log = LoggerFactory.getLogger(AbstractRegistryCenterFactory.class);

    @Autowired
    private RegistryCenterInfo registryCenterInfo;

    public AbstractRegistryCenterFactory() {

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        CuratorFramework curatorFramework = getZooKeeper();

        if (curatorFramework.checkExists().forPath(ZkPathConstant.REGISTRY) == null) {
            curatorFramework
                    .create()
                    .withMode(CreateMode.PERSISTENT)
                    .forPath(ZkPathConstant.REGISTRY);
        }
    }

    @Override
    public void destroy() throws Exception {
        // 循环销毁所有的服务
        for (ServiceInfo serviceInfo : serviceMap.values()) {
            log.info("销毁服务 " + serviceInfo);

            unregister(serviceInfo);
        }

        getZooKeeper()
                .delete()
                .forPath(ZkPathConstant.REGISTRY);
    }

    @SneakyThrows
    public CuratorFramework getZooKeeper() {
        if (curatorFramework == null) {
            synchronized (this) {
                if (curatorFramework == null) {
                    curatorFramework = CuratorFrameworkFactory
                            .builder()
                            .connectString(registryCenterInfo.getZkAddress())
                            .connectionTimeoutMs(1000)
                            .retryPolicy(new RetryNTimes(3, 2000))
                            .build();

                    curatorFramework.start();
                    curatorFramework.blockUntilConnected();

                    log.info("zk 服务器 连接成功");
                }
            }
        }

        return curatorFramework;
    }
}
